iT邦幫忙

2026 iThome 鐵人賽

DAY 28
0
IT Operation

Docker 新手村:從容器到 PostgreSQL 的實戰之路系列 第 29 篇

Day 28 - Node.js API 串接 PostgreSQL:讓前端可以存取資料庫

  • 分享至 

  • xImage
  •  

學習目標

  • 認識 API 在系統中的角色
  • 使用 Express 建立簡單的後端 API
  • 使用 Node.js 查詢 PostgreSQL
  • 建立員工資料的 GET API
  • 建立新增員工的 POST API
  • 了解前端、後端與資料庫之間的流程

從資料庫連線到 API

Day 27 已經建立了排班專題需要的 employees 與 schedules Table。

之前 Node.js 雖然可以直接查詢 PostgreSQL,但真正的系統通常不會讓前端直接操作資料庫,而是透過後端 API 處理。

整體架構會變成:

前端
 │
 │ HTTP Request
 ↓
Node.js API
 │
 │ SQL
 ↓
PostgreSQL
 │
 ↓
employees / schedules

今天就要建立簡單的 Express API,讓程式可以透過 API 取得與新增員工資料。


安裝 Express

首先在 Node.js 專案中安裝 Express:

npm install express

之前已經安裝過:

npm install pg dotenv

因此目前會使用到:

express → 建立 API
pg      → 連線 PostgreSQL
dotenv  → 讀取環境變數

建立 PostgreSQL Pool

先建立基本的 Express 與 PostgreSQL 連線:

require("dotenv").config();

const express = require("express");
const { Pool } = require("pg");

const app = express();

app.use(express.json());

const pool = new Pool({
  host: process.env.DB_HOST,
  port: Number(process.env.DB_PORT),
  user: process.env.DB_USER,
  password: process.env.DB_PASSWORD,
  database: process.env.DB_NAME
});

app.listen(3000, () => {
  console.log("Server running on port 3000");
});

這次使用的是:

Pool

而不是 Day 24 使用的 Client。

因為 API 會不斷收到不同 Request,使用 Pool 可以管理與重複使用資料庫連線,比每次 Request 都重新建立一個 Client 更適合後端服務。


建立 GET API

第一個 API 用來取得所有員工資料:

app.get("/employees", async (req, res) => {
  try {
    const result = await pool.query(
      "SELECT * FROM employees ORDER BY id"
    );

    res.json(result.rows);
  } catch (err) {
    console.error(err);
    res.status(500).json({
      message: "取得員工資料失敗"
    });
  }
});

當使用者請求:

GET /employees

Node.js 就會執行:

SELECT * FROM employees ORDER BY id;

最後將 PostgreSQL 查詢結果轉成 JSON 回傳。


GET API 的流程

整個流程可以整理成:

GET /employees
      │
      ↓
Express
      │
      ↓
SELECT * FROM employees
      │
      ↓
PostgreSQL
      │
      ↓
result.rows
      │
      ↓
JSON Response

例如回傳:

[
  {
    "id": 1,
    "name": "小明",
    "employee_type": "正職"
  },
  {
    "id": 2,
    "name": "小美",
    "employee_type": "兼職"
  }
]

建立 POST API

除了查詢員工,也可以建立新增員工的 API:

app.post("/employees", async (req, res) => {
  const { name, employee_type } = req.body;

  try {
    const result = await pool.query(
      `INSERT INTO employees (name, employee_type)
       VALUES ($1, $2)
       RETURNING *`,
      [name, employee_type]
    );

    res.status(201).json(result.rows[0]);
  } catch (err) {
    console.error(err);
    res.status(500).json({
      message: "新增員工失敗"
    });
  }
});

前端只需要送出:

{
  "name": "小雨",
  "employee_type": "兼職"
}

Node.js 就會將資料新增到 PostgreSQL。


為什麼 SQL 使用 $1、$2?

這次沒有直接把變數放進 SQL:

`INSERT INTO employees VALUES ('${name}', '${employee_type}')`

而是使用:

VALUES ($1, $2)

再另外傳入:

[name, employee_type]

這種方式叫做 Parameterized Query(參數化查詢)。

除了讓 SQL 與資料分開之外,也可以降低 SQL Injection 的風險,因此使用者輸入的資料不應直接拼接到 SQL 字串中。


讓 Docker 可以存取 API

如果 Node.js 也在 Docker Compose 中,可以替 app 加入 Port:

app:
  build: .
  container_name: my-node-app
  ports:
    - "3000:3000"
  env_file:
    - .env
  depends_on:
    - postgres

接著重新建立:

docker compose up -d --build

現在就可以透過:

localhost:3000

存取 Node.js API。

例如:

GET http://localhost:3000/employees

現在的完整流程

做到這裡,排班專題已經開始形成完整的前後端資料流程:

瀏覽器 / 前端
      │
      │ localhost:3000
      ↓
Node.js + Express
      │
      │ postgres:5432
      ↓
PostgreSQL
      │
      ├── employees
      └── schedules

前端不需要知道 PostgreSQL 的帳號密碼,只需要透過 API 與後端溝通。


常見錯誤與修正

  • ❌ req.body 取得不到資料 → ✅ 加入 app.use(express.json())
  • ❌ Node.js 無法連線 PostgreSQL → ✅ 確認 .env 與 DB_HOST
  • ❌ Container 中使用 localhost 找 PostgreSQL → ✅ 使用 Service Name postgres
  • ❌ 外部無法存取 API → ✅ 在 Compose 加入 3000:3000
  • ❌ 直接把使用者輸入拼進 SQL → ✅ 使用 $1、$2 參數化查詢
  • ❌ API 出現 500 → ✅ 查看 Node.js Logs 與 PostgreSQL 錯誤訊息

今日小挑戰(可交付)

  • [ ] 安裝 Express
  • [ ] 使用 Pool 連線 PostgreSQL
  • [ ] 建立 GET /employees
  • [ ] 成功取得員工 JSON 資料
  • [ ] 建立 POST /employees
  • [ ] 使用參數化 SQL 新增員工
  • [ ] 在 Compose 開放 3000 Port
  • [ ] 確認新增的資料有進入 PostgreSQL

DAY28 心得

今天終於把 Node.js、Express 和 PostgreSQL 真正串在一起。之前雖然 Node.js 已經可以查詢資料庫,但今天加入 API 後,整個專題的資料流程變得更完整。

前端不需要直接操作 PostgreSQL,而是先把 Request 傳給 Express,再由後端執行 SQL,最後把結果用 JSON 回傳。這也讓我更清楚前端、後端和資料庫各自負責的工作。

另外今天也學到參數化查詢,原本可能會很直覺地把變數直接放進 SQL 字串,但使用 $1、$2 的方式會更加安全。

目前已經可以透過 API 查詢與新增員工,接下來就可以把 PostgreSQL、Node.js 和整個 Docker Compose 環境整理在一起,完成一套可以快速建立的開發環境。


上一篇
Day 27 - 設計員工與排班資料表:把專題資料放進 PostgreSQL
下一篇
Day 29 - 用 Docker Compose 建立完整開發環境
系列文
Docker 新手村:從容器到 PostgreSQL 的實戰之路 共 31 篇
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言